package gateway.server.route;

import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author Jin Zheng
 * @since 1.0 2020-09-10
 */
public class ChannelRoute
{
	private static Logger logger = LoggerFactory.getLogger(ChannelRoute.class);

	private final ChannelGroup channelGroup;
	private final Map<Long, ChannelId> idChMap;
	private final Map<ChannelId, Set<Long>> chIdMap;

	public ChannelRoute()
	{
		this.channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
		this.idChMap = new HashMap<>();
		this.chIdMap = new HashMap<>();
	}

	public Channel get(Long id)
	{
		ChannelId chId = idChMap.get(id);
		if (chId == null)
			return null;

		return channelGroup.find(chId);
	}

	public void add(Long id, Channel ch)
	{
		ChannelId chId = ch.id();
		idChMap.put(id, chId);
		channelGroup.add(ch);
		Set<Long> idSet = chIdMap.computeIfAbsent(chId, k -> new HashSet<>());
		idSet.add(id);
		logger.info("Add channel, channel: {}, id: {}", chId, id);
	}

	public void remove(Channel ch)
	{
		ChannelId chId = ch.id();
		Set<Long> idSet = chIdMap.get(chId);
		chIdMap.remove(chId);
		if (idSet == null || idSet.isEmpty())
			return;

		for (Long id : idSet)
		{
			idChMap.remove(id);
		}
		logger.info("Remove channel, channel: {}, id: {}", chId, idSet);
	}

}
